/**************************************************************************************************
**                                                                                               **
**  文件名称:  app_usbh_test.c                                                                    **
**  版权所有:  CopyRight @ Xiamen Yaxon NetWork CO.LTD. 2017                                     **
**  文件描述:  USB文件系统测试模块                                                               **
**  ===========================================================================================  **
**  创建信息:  | 2018-7-19 | LEON | 创建本模块                                                   **
**  ===========================================================================================  **
**  修改信息:  单击此处添加....                                                                  **
**************************************************************************************************/
#include "app_include.h"
#include "app_usbh_test.h"

#ifdef USB_HOST

/*************************************************************************************************/
/*                           模块宏定义                                                          */
/*************************************************************************************************/
#define PERIOD_USBHTEST      _SECOND, 1

#define USBH_READDLEN        36                                                /* 每次读取的字节数 */
#define USBH_FILENAME        "test.dat"                                        /* 测试文件的文件名 */

/*************************************************************************************************/
/*                           定义模块变量                                                        */
/*************************************************************************************************/
static INT8U          s_usbhtesttmr;
static BOOLEAN        s_usbhfsinitd;                                           /* USB文件系统已被初始化 */
static BOOLEAN        s_usbhfsready;                                           /* USB文件系统已就绪 */
static INT32U         s_usbhreadlen;                                           /* 已经读取过的长度 */
static DIR            s_usbhdiskdir;                                           /* 当前操作的磁盘目录 */
static FIL            s_usbhfilehdl;                                           /* 当前操作的文件句柄 */
static FILINFO        s_usbhfilinfo;                                           /* 当前操作的文件信息 */

/**************************************************************************************************
**  函数名称:  ReadFileTestOpt
**  功能描述:  读文件测试操作
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void ReadFileTestOpt(void)
{
    INT32U  BytesRead;
    FRESULT fresult;
    INT8U   buffer[USBH_READDLEN];
    
    if ((s_usbhreadlen + USBH_READDLEN) > s_usbhfilinfo.fsize) {               /* 读取的位置即将超出文件总长度 */
        #if DEBUG_COMM > 0
        Debug_PrintStr("file is about to read_to_end!!!\r\n");
        #endif
        s_usbhfsinitd = FALSE;
        s_usbhfsready = FALSE;
        return;
    }
    
    fresult = f_lseek(&s_usbhfilehdl, s_usbhreadlen);                          /* 跳转到指定的位置处继续读取 */
    
    #if DEBUG_COMM > 0
    Debug_SysPrint("f_seek file to %d bytes. result: %d\r\n", s_usbhreadlen, fresult);
    #endif
    
    if (fresult != FR_OK) {
        #if DEBUG_COMM > 0
        Debug_PrintStr("file seek error!!!\r\n");
        #endif
        return;
    }
    
    fresult = f_read(&s_usbhfilehdl, buffer, USBH_READDLEN, &BytesRead);       /* 读取文件内容 */
    
    #if DEBUG_COMM > 0
    Debug_SysPrint("f_read file %d bytes. result: %d\r\n", USBH_READDLEN, fresult);
    #endif
    
    if (fresult != FR_OK) {
        #if DEBUG_COMM > 0
        Debug_PrintStr("file read error!!!\r\n");
        #endif
        return;
    }
    
    if (BytesRead != USBH_READDLEN) {
        #if DEBUG_COMM > 0
        Debug_PrintStr("file read len error!!!\r\n");
        #endif
        return;
    }
    
    s_usbhreadlen += USBH_READDLEN;
    
    #if DEBUG_COMM > 0
    Debug_PrintStr("file data: ");
    Debug_PrintHex(buffer, USBH_READDLEN);
    #endif
}

/**************************************************************************************************
**  函数名称:  CheckFileSystem
**  功能描述:  检测USB文件系统
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void CheckFileSystem(void)
{
    FATFS    fatfs;
    FRESULT  fresult;
    char path[] = "";
    
    /*************************************************************************************************/
    //                           步骤1：挂载整个设备
    /*************************************************************************************************/
    
    fresult = f_mount(&fatfs, path, 1);
    
    if (fresult != FR_OK) {
        #if DEBUG_COMM > 0
        Debug_SysPrint("USB_Device Mount Fail %d...\r\n", fresult);
        #endif
        return;
    }
    
    #if DEBUG_COMM > 0
    Debug_SysPrint("USB_Device Mount Success...\r\n");
    #endif
    
    /*************************************************************************************************/
    //                           步骤2：判断磁盘读写属性
    /*************************************************************************************************/
    
    if (USBH_MSC_Param.MSWriteProtect == DISK_WRITE_PROTECTED) {
        #if DEBUG_COMM > 0
        Debug_SysPrint("USB_Device is write protected...\r\n");
        #endif
        return;
    }
    
    #if DEBUG_COMM > 0
    Debug_SysPrint("USB_Device and FileSystem is Ready...\r\n");
    #endif

    /*************************************************************************************************/
    //                           步骤3：打开盘符根目录
    /*************************************************************************************************/
    
    fresult = f_opendir(&s_usbhdiskdir, path);
    
    #if DEBUG_COMM > 0
    Debug_SysPrint("f_opendir \"%s\". result: %d\r\n", path, fresult);
    #endif
    
    if (fresult != FR_OK) {
        #if DEBUG_COMM > 0
        Debug_PrintStr("dir open error!!!\r\n");
        #endif
        return;
    }
    
    /*************************************************************************************************/
    //                           步骤4：获取文件状态及信息
    /*************************************************************************************************/
    
    fresult = f_stat(USBH_FILENAME, &s_usbhfilinfo);
    
    #if DEBUG_COMM > 0
    Debug_SysPrint("f_stat file \"%s\". result: %d\r\n", USBH_FILENAME, fresult);
    #endif
    
    if (fresult != FR_OK) {
        #if DEBUG_COMM > 0
        Debug_PrintStr("file stat error!!!\r\n");
        #endif
        return;
    }
    
    #if DEBUG_COMM > 0
    Debug_SysPrint("file size %.8d, modfy date %d, modfy time %d, attrib %d\r\n", s_usbhfilinfo.fsize, s_usbhfilinfo.fdate, s_usbhfilinfo.ftime, s_usbhfilinfo.fattrib);
    #endif
    
    /*************************************************************************************************/
    //                           步骤5：打开文件
    /*************************************************************************************************/
    
    fresult = f_open(&s_usbhfilehdl, USBH_FILENAME, FA_READ);
    
    #if DEBUG_COMM > 0
    Debug_SysPrint("f_open file \"%s\". result: %d\r\n", USBH_FILENAME, fresult);
    #endif
    
    if (fresult != FR_OK) {
        #if DEBUG_COMM > 0
        Debug_PrintStr("file open error!!!\r\n");
        #endif
        return;
    }
    
    s_usbhfsready = TRUE;
    s_usbhreadlen = 0;
}

/**************************************************************************************************
**  函数名称:  USBH_TestStatInform
**  功能描述:  USB设备状态通知回调函数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void USBH_TestStatInform(USBH_STAT_E stat)
{
    switch (stat)
    {
        case USBH_STAT_INIT:
            #if DEBUG_COMM > 0
            Debug_SysPrint("USB_Host Init...\r\n");
            #endif
            break;
            
        case USBH_STAT_DEINIT:
            #if DEBUG_COMM > 0
            Debug_SysPrint("USB_Host Deinit...\r\n");
            #endif
            break;
            
        case USBH_STAT_ATTACHED:
            #if DEBUG_COMM > 0
            Debug_SysPrint("USB_Host Attached...\r\n");
            #endif
            break;
            
        case USBH_STAT_RESETDEVICE:
            #if DEBUG_COMM > 0
            Debug_SysPrint("USB_Host Reset Device...\r\n");
            #endif
            break;
            
        case USBH_STAT_OVERCURRENT:
            #if DEBUG_COMM > 0
            Debug_SysPrint("USB_Host Over Current...\r\n");
            #endif
            break;
            
        case USBH_STAT_DISCONNECTED:
            #if DEBUG_COMM > 0
            Debug_SysPrint("USB_Host Disconnected...\r\n");
            #endif
            s_usbhfsinitd = FALSE;
            s_usbhfsready = FALSE;
            f_mount(NULL, NULL, 0);
            OSL_PostSysMsg(MSG_USB_NOTINST, 0, 0, FALSE);
            break;
                        
        case USBH_STAT_ENUMERATIONDONE:
            #if DEBUG_COMM > 0
            Debug_SysPrint("USB_Host Enum Done...\r\n");
            #endif
            s_usbhfsinitd = FALSE;
            s_usbhfsready = FALSE;
            OSL_PostSysMsg(MSG_USB_DEVVALD, 0, 0, FALSE);
            break;
            
        case USBH_STAT_MSC_APPLICATION:
            #if DEBUG_COMM > 0
            Debug_SysPrint("USB_Host Application...\r\n");
            #endif
            if (s_usbhfsinitd == FALSE) {
                s_usbhfsinitd = TRUE;
                CheckFileSystem();
            }
            break;
            
        case USBH_STAT_NOTSUPPORTED:
            #if DEBUG_COMM > 0
            Debug_SysPrint("USB_Host NOT Surpported...\r\n");
            #endif
            OSL_PostSysMsg(MSG_USB_DEVEROR, 0, 0, FALSE);
            break;
            
        case USBH_STAT_UNRECOVEREDERROR:
            #if DEBUG_COMM > 0
            Debug_SysPrint("USB_Host Error...\r\n");
            #endif
            OSL_PostSysMsg(MSG_USB_DEVEROR, 0, 0, FALSE);
            break;

        default:
            #if DEBUG_COMM > 0
            Debug_SysPrint("USBH_TestStatInform: Stat Error!!!\r\n");
            #endif
            break;
    }
}

/**************************************************************************************************
**  函数名称:  USBH_TestTmrProc
**  功能描述:  定时器
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void USBH_TestTmrProc(void)
{
    if (s_usbhfsready == FALSE) {                                              /* 确认U盘文件系统就绪 */
        return;
    }
    
    ReadFileTestOpt();                                                         /* 尝试读取U盘数据内容 */
}

/**************************************************************************************************
**  函数名称:  APP_UsbhTestInit
**  功能描述:  模块初始化函数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void APP_UsbhTestInit(void)
{
    s_usbhtesttmr = OSL_CreateTimer(USBH_TestTmrProc);
    OSL_StartTimer(s_usbhtesttmr, PERIOD_USBHTEST);
    
    USBH_USR_RegStatHdl(&USBH_TestStatInform);                                 /* 注册回调函数 */
}

#endif


